package com.nstc.sftpExchange.config.sftp;

import cn.hutool.core.lang.Assert;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class SftpTemplate {

    private String name;

    private final FtpConnectionKey sftpConnectionKey;

    private final SftpRoutingPool sftpRoutingPool;

    private static final ThreadLocal<ConnectionHandler<FtpConnection>> local = new ThreadLocal<>();

    public SftpTemplate(String name, FtpConnectionKey sftpConnectionKey, SftpRoutingPool sftpRoutingPool){
        this.name = name;
        this.sftpConnectionKey = sftpConnectionKey;
        this.sftpRoutingPool = sftpRoutingPool;
    }


    public <T> T execute(ChannelCallback<T> action) throws RuntimeException {
        Assert.notNull(action, "Callback object must not be null");
        FtpConnection sftpConnection;
        try {
            sftpConnection = getConnection(sftpConnectionKey);
            return action.doInChannel(sftpConnection);
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        } finally {
            releaseConnection(sftpConnectionKey);
        }
    }

    /**
     * 获取连接，同一个线程使用同一个连接
     *
     * @return FtpConnection
     * @throws Exception Exception
     */
    private FtpConnection getConnection(FtpConnectionKey sftpConnectionKey) throws Exception {
        ConnectionHandler<FtpConnection> connectionHandler = local.get();
        if (connectionHandler == null) {
            //该线程没有分配连接
            connectionHandler = new ConnectionHandler<>(sftpRoutingPool.getPool(sftpConnectionKey).borrowObject());
            local.set(connectionHandler);
            log.debug("borrow conn:{}",connectionHandler.getConn());
        }
        //引用计数+1
        connectionHandler.requested(name);
        return connectionHandler.getConn();
    }

    /**
     * 释放连接
     */
    public void releaseConnection(FtpConnectionKey sftpConnectionKey) {
        ConnectionHandler<FtpConnection> connectionHandler = local.get();
        if (connectionHandler != null) {
            //引用计数-1
            int referenceCount = connectionHandler.released();
            if (referenceCount <= 0) {
                //清除TheadLocal中缓存的连接对象，防止内存泄露
                local.remove();
                //引用计数小于等于0，归还连接
                sftpRoutingPool.getPool(sftpConnectionKey).returnObject(connectionHandler.getConn());
                log.debug("return conn:{}",connectionHandler.getConn());
            }
        }
    }


}
